<?php
/**
 * DAO_Mysql
 * 
 * 作者:  姚刚 (yaogang@the9sense.com)
 * 创建时间: 2011-03-06 01:28:18
 * 修改记录: 
 * 
 * $Id: Mysql.php 18 2011-04-17 12:50:07Z coosuu $
 */

class DAO_Mysql {

    /**
     * getRow 
     * 
     * @param  mixed $table 
     * @param  mixed $conditions 
     * @param  array $params 
     * @param  string $columns 
     * @return void
     */
    public static function getRow($table, $conditions = null, $params = array(), $columns = array('*')) {

        if ($params && !is_array($params)) {
            throw new InvalidArgumentException('$params must be an array');
        }

        if (!is_array($columns)) {
            throw new InvalidArgumentException('$columns must be an array');
        }

        $allowedFields = Config::get('DB.' . $table . '.fields.allowed');
        if (!is_array($allowedFields)) {
            throw new InvalidArgumentException('Param $allowedFields Cannt Be Empty');
        }

        if ($columns == array('*') || !$columns) {
            $columns = $allowedFields;
        }

        $diff = array_diff($columns, $allowedFields);
        if ($diff) {
            throw new InvalidArgumentException("Invalid Field(" . join(',', $diff) . ")");
        }

        try {
            $dal = new DataStore($table);

            return $dal->getRow($conditions, $params, $columns);
        } catch (Exception $e) {
            throw new DAO_Exception($e);
        }
    }

    /**
     * getRowByKey 
     * 
     * @param  mixed $table 
     * @param  mixed $pk 
     * @param  mixed $pkValue 
     * @param  string $columns 
     * @return void
     */
    public static function getRowByKey($table, $pk, $pkValue, $columns = array('*')) {

        if (!is_array($columns)) {
            throw new InvalidArgumentException('$columns must be an array');
        }

        $allowedFields = Config::get('DB.' . $table . '.fields.allowed');
        if (!is_array($allowedFields)) {
            throw new InvalidArgumentException('Param $allowedFields Cannt Be Empty');
        }

        if ($columns == array('*') || !$columns) {
            $columns = $allowedFields;
        }

        $diff = array_diff($columns, $allowedFields);
        if ($diff) {
            throw new InvalidArgumentException("Invalid Field(" . join(',', $diff) . ")");
        }

        try {
            $conditions = $pk . ' = ? ';
            $params = array($pkValue);
            return self::getRow($table, $conditions, $params, $columns);
        } catch (Exception $e) {
            throw new DAO_Exception($e);
        }
    }

    /**
     * getAll 
     * 
     * @param  mixed $table 
     * @param  mixed $conditions 
     * @param  array $params 
     * @param  string $columns 
     * @param  array $pageOptions 
     * @param  array $order 
     * @return void
     */
    public static function getAll($table, $conditions = null, $params = array(), $columns = array('*'), $pageOptions = array(), $order = array()) {

        if ($params && !is_array($params)) {
            throw new InvalidArgumentException('$params must be an array');
        }

        if ($columns && !is_array($columns)) {
            throw new InvalidArgumentException('$columns must be an array');
        }

        $allowedFields = Config::get('DB.' . $table . '.fields.allowed');
        if (!is_array($allowedFields)) {
            throw new InvalidArgumentException('Param $allowedFields Cannt Be Empty');
        }

        if ($columns == array('*') || !$columns) {
            $columns = $allowedFields;
        }

        $diff = array_diff($columns, $allowedFields);
        if ($diff) {
            throw new InvalidArgumentException("Invalid Field(" . join(',', $diff) . ")");
        }
        if ($pageOptions && !is_array($pageOptions)) {
            throw new InvalidArgumentException('$pageOptions must be an array');
        }

        if ($order && !is_array($order)) {
            throw new InvalidArgumentException('$order must be an array');
        }

        $start = $limit = 0;
        if ($pageOptions['currentPage'] && $pageOptions['perPage']) {
            $start = ($pageOptions['currentPage'] - 1) * $pageOptions['perPage'];
            $limit = $pageOptions['perPage'];
        }

        try {
            $dal = new DataStore($table);
            return $dal->getAll($conditions, $params, $columns, $start, $limit, $order);
        } catch (Exception $e) {
            throw new DAO_Exception($e);
        }
    }

    /**
     * getOne 
     * 
     * @param  mixed $table 
     * @param  mixed $conditions 
     * @param  array $params 
     * @param  string $columns 
     * @return void
     */
    public static function getOne($table, $conditions = null, $params = array(), $columns = array('*')) {

        if ($params && !is_array($params)) {
            throw new InvalidArgumentException('$params must be an array');
        }

        $allowedFields = Config::get('DB.' . $table . '.fields.allowed');
        if (!is_array($allowedFields)) {
            throw new InvalidArgumentException('Param $allowedFields Cannt Be Empty');
        }

        if ($columns == array('*') || !$columns) {
            $columns = $allowedFields;
        }

        $diff = array_diff($columns, $allowedFields);
        if ($diff) {
            throw new InvalidArgumentException("Invalid Field(" . join(',', $diff) . ")");
        }

        try {
            $dal = new DataStore($table);
            return $dal->getOne($conditions, $params);
        } catch (Exception $e) {
            throw new DAO_Exception($e);
        }
    }

    /**
     * add 
     * 
     * @param  mixed $table 
     * @param  mixed $data 
     * @return void
     */
    public static function add($table, $data) {

        $allowedFields = Config::get('DB.' . $table . '.fields.allowed');
        $requiredFields = Config::get('DB.' . $table . '.fields.required');

        if (!is_array($requiredFields)) {
            throw new InvalidArgumentException('Praram $RequiredFields Cannt Be Empty!');
        }

        if (!is_array($allowedFields) || !$allowedFields) {
            throw new InvalidArgumentException('Praram $allowedFields Cannt Be Empty!');
        }

        $fields = array_keys($data);
        $result = array_diff($fields, $allowedFields);
        if ($result) {
            throw new InvalidArgumentException("Invalid Field(" . join(',', $result) . ")");
        }

        $result = array_diff($requiredFields, $fields);
        if ($result) {
            throw new InvalidArgumentException(join(',', $result) . " is Required.");
        }

        try {
            $dal = new DataStore($table);
            $dal->save($data);
            return $dal->getLastInsertId();
        } catch (PDOException $e) {
            switch ($e->getCode()) {
                case '23000':
                    throw new DAO_DuplicateException($e);
                    break;
                default:
                    throw new DAO_Exception($e);
            }
        }
    }

    /**
     * update 
     * 
     * @param  mixed $table 
     * @param  mixed $data 
     * @param  mixed $conditions 
     * @param  array $params 
     * @return void
     */
    public static function update($table, $data, $conditions = null, $params = array()) {

        $allowedFields = Config::get('DB.' . $table . '.fields.allowed');
        if (!is_array($allowedFields)) {
            throw new InvalidArgumentException('Param $allowedFields Cannt Be Empty');
        }

        $fields = array_keys($data);
        $result = array_diff($fields, $allowedFields);
        if ($result) {
            throw new InvalidArgumentException("Invalid Field(" . join(',', $result) . ")");
        }

        try {

            $dal = new DataStore($table);
            return $dal->save($data, $conditions, $params);
        } catch (PDOException $e) {
            throw new DAO_Exception($e);
        }
    }

    /**
     * updateByKey 
     * 
     * @param  mixed $table 
     * @param  mixed $data 
     * @param  mixed $pkValue 
     * @return void
     */
    public static function updateByKey($table, $data, $pkValue) {

        $allowedFields = Config::get('DB.' . $table . '.fields.allowed');
        $pk = Config::get('DB.' . $table . '.fields.pk');

        if (!is_array($allowedFields)) {
            throw new InvalidArgumentException('Param $allowedFields Cannt Be Empty');
        }

        if (!$pk) {
            throw new InvalidArgumentException('Pk Cannt Be Empty');
        }

        $fields = array_keys($data);
        $result = array_diff($fields, $allowedFields);
        if ($result) {
            throw new InvalidArgumentException("Invalid Field(" . join(',', $result) . ")");
        }

        try {
            $conditions = $pk . ' = ? ';
            $params = array($pkValue);
            return self::update($table, $data, $conditions, $params, $allowedFields);
        } catch (PDOException $e) {
            throw new DAO_Exception($e);
        }
    }

    /**
     * remove 
     * 
     * @param  mixed $table 
     * @param  mixed $conditions 
     * @param  array $params 
     * @return void
     */
    public static function remove($table, $conditions = null, $params = array()) {

        try {
            $dal = new DataStore($table);
            return $dal->remove($conditions, $params);
        } catch (PDOException $e) {
            throw new DAO_Exception($e);
        }
    }

    /**
     * removeByKey 
     * 
     * @param  mixed $table 
     * @param  mixed $pk 
     * @param  mixed $pkValue 
     * @return void
     */
    public static function removeByKey($table, $pk, $pkValue) {

        $conditions = $pk . ' = ? ';
        $params = array($pkValue);
        try {
            return self::remove($table, $conditions, $params);
        } catch (PDOException $e) {
            throw new DAO_Exception($e);
        }
    }

    /**
     * incr 
     * 
     * @return void
     */
    public static function incr() {

    }

    /**
     * decr 
     * 
     * @return void
     */
    public static function decr() {

    }

    /**
     * count 
     * 
     * @param  mixed $table 
     * @param  mixed $conditions 
     * @param  array $params 
     * @return void
     */
    public static function count($table, $conditions = null, $params = array()) {

        if ($params && !is_array($params)) {
            throw new InvalidArgumentException('$params must is an array');
        }

        try {
            $dal = new DataStore($table);
            $num = $dal->count($conditions, $params);
        } catch (Exception $e) {
            throw new DAO_Exception($e);
        }

        return intval($num);
    }

    /**
     * buildInSQLClause 
     * 
     * @param  mixed $data 
     * @param  mixed $sqlParams 
     * @return void
     */
    public static function buildInSQLClause($data, &$sqlParams) {

        if (!is_array($data)) {
            $data = array($data);
        }

        $params = array();
        foreach ($data as $v) {
            $params[] = '?';
            $sqlParams[] = $v;
        }

        return join(',', $params);
    }
}
